﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using Kooboo.Extensions;
using Kooboo.Globalization;

namespace Kooboo.Web.Areas.Commerce.Binders
{
    using Kooboo.Commerce;
    
    using Kooboo.Web.Areas.Commerce.Binders;
    using Kooboo.Web.Areas.Commerce.Web.UI;
    using Kooboo.IoC;

    public class ProductBinder : EntityBinder
    {

        protected override string[] SkipProperties
        {
            get
            {
                return new string[] { "ProductCustomFields", "SaleItems", "Categories", "ProductType", "Brand","ProductImages","Tax" };
            }
        }
        protected override object CreateModel(ControllerContext controllerContext,
            ModelBindingContext bindingContext, Type modelType)
        {

            var model = ObjectContainer.CreateInstance<IProduct>();

            var form = controllerContext.HttpContext.Request.Form;

            model.Id = int.Parse(form["Id"]);


            int productTypeId;

            if (int.TryParse(form["ProductType.Id"], out productTypeId))
            {
                var productType = ObjectContainer.CreateInstance<IProductType>();
                productType.Id = productTypeId;
                model.ProductType = productType;
            }

            var brandid = form["BrandId"];

            if (string.IsNullOrWhiteSpace(brandid) == false)
            {
                var brand = ObjectContainer.CreateInstance<IBrand>();
                brand.Id = int.Parse(brandid);
                model.Brand = brand;
            }


            int taxId;

            if (int.TryParse(form["Tax.Id"], out taxId))
            {
                var tax = ObjectContainer.CreateInstance<ITax>();
                tax.Id = taxId;

                model.Tax = tax;
            }

            #region CustomFields
            model.ProductCustomFields = new List<IProductCustomField>();

            for (var i = 0; i < int.MaxValue; i++)
            {
                var prefix = "CustomFields[" + i.ToString() + "]";

                var name = prefix + ".Name";

                var value = form[name];
                if (string.IsNullOrWhiteSpace(value))
                {
                    break;
                }


                var id = form[prefix + ".Id"];


                var field = ObjectContainer.CreateInstance<IProductCustomField>();
                field.Id = int.Parse(id);

                field.Value = value;

                field.Product = model;


                var customFieldId = int.Parse(form[prefix + ".CustomField.Id"]);

                var customField = model.ProductType.CustomFields.Where(n => n.Id == customFieldId).FirstOrDefault();

                field.CustomField = customField;

                var errors = customField.Validate(field.Value);

                if (errors.Count > 0)
                {
                    ModelState state = new ModelState();

                    for (var n = 0; n < errors.Count; n++)
                    {
                        state.Errors.Add(errors[n]);
                    }

                    bindingContext.ModelState.Add(name, state);
                }

                if (customField.DataFormat == DataFormat.Number)
                {
                    decimal number;
                    if (decimal.TryParse(field.Value, out number))
                    {
                        field.NumberValue = number;
                    }
                    else
                    {
                        field.NumberValue = null;

                        if (bindingContext.ModelState.ContainsKey(name) == false)
                        {
                            bindingContext.ModelState.Add(new KeyValuePair<string, ModelState>(name, new ModelState()));
                        }

                        bindingContext.ModelState[name].Errors.Add(field.Value + " is an invalid numeric string".Localize());
                    }
                }
                else if (customField.DataFormat == DataFormat.DateTime)
                {
                    DateTime date;
                    if (DateTime.TryParse(field.Value, out date))
                    {
                        field.DateTimeValue = date;
                    }
                    else
                    {
                        field.DateTimeValue = null;

                        if (bindingContext.ModelState.ContainsKey(name) == false)
                        {
                            bindingContext.ModelState.Add(new KeyValuePair<string, ModelState>(name, new ModelState()));
                        }

                        bindingContext.ModelState[name].Errors.Add(field.Value + " is an invalid datetime string.".Localize());
                    }
                }

                model.ProductCustomFields.Add(field);

            }
            #endregion

            #region SaleItems
            var saleItems = new List<ISaleItem>();

            var saleItemIndexes = form["SaleItems.index"];

            if (saleItemIndexes != null)
            {
                foreach (var i in saleItemIndexes.Split(','))
                {
                    var prefix = "SaleItems[" + i.ToString() + "]";

                    var item = ObjectContainer.CreateInstance<ISaleItem>();
                    item.Id = int.Parse(form[prefix + ".Id"]);
                    item.SKU = form[prefix + ".SKU"];
                    decimal purchasePrice;
                    if (decimal.TryParse(form[prefix + ".PurchasePrice"], out purchasePrice))
                    {
                        item.PurchasePrice = purchasePrice;
                    }
                    else
                    {
                        item.PurchasePrice = decimal.Zero;
                    }

                    decimal retailPrice;
                    if (decimal.TryParse(form[prefix + ".RetailPrice"], out retailPrice))
                    {
                        item.RetailPrice = retailPrice;
                    }
                    else
                    {
                        item.RetailPrice = decimal.Zero;
                    }

                    int stock;

                    if (int.TryParse(form[prefix + ".Stock"], out stock))
                    {
                        item.Stock = stock;
                    }
                    else
                    {
                        item.Stock = 0;
                    }

                    int deliveryDays;
                    if (int.TryParse(form[prefix + ".DeliveryDays"], out deliveryDays))
                    {
                        item.DeliveryDays = deliveryDays;
                    }
                    else
                    {
                        item.DeliveryDays = 0;
                    }



                    item.ProductVariations = new List<IProductVariation>();

                    var productVariationIndexes = form[prefix + ".ProductVariations.index"];
                    if (productVariationIndexes != null)
                    {
                        foreach (var v in productVariationIndexes.Split(','))
                        {
                            var productVariation = ObjectContainer.CreateInstance<IProductVariation>();

                            var productVariation_prefix = prefix + ".ProductVariations[" + v + "]";

                            productVariation.Id = int.Parse(form[productVariation_prefix + ".Id"]);
                            productVariation.Value = form[productVariation_prefix + ".Value"];

                            DateTime dateTimeValue;
                            if (DateTime.TryParse(productVariation.Value, out dateTimeValue))
                            {
                                productVariation.DateTimeValue = dateTimeValue;
                            }
                            else
                            {
                                productVariation.DateTimeValue = null;
                            }

                            decimal numberValue;
                            if (decimal.TryParse(productVariation.Value, out numberValue))
                            {
                                productVariation.NumberValue = numberValue;
                            }
                            else
                            {
                                productVariation.NumberValue = null;
                            }

                            var variation = ObjectContainer.CreateInstance<IVariation>();
                            variation.Id = int.Parse(form[productVariation_prefix + ".Variation.Id"]);

                            productVariation.Variation = variation;

                            item.ProductVariations.Add(productVariation);
                        }
                    }

                    saleItems.Add(item);
                }
            }

            model.SaleItems = saleItems;
            #endregion

            model.ProductImages = new List<IProductImage>();

            var productImageIndexes = form["ProductImages.index"];

            if (productImageIndexes != null)
            {
                foreach (var i in productImageIndexes.Split(','))
                {
                    var prefix = "ProductImages[" + i + "]";
                    var image = ObjectContainer.CreateInstance<IProductImage>();
                    image.Id = int.Parse(form[prefix + ".Id"]);
                    image.Name = form[prefix + ".Name"];
                    image.CoverImage = bool.Parse(form[prefix + ".CoverImage"]);

                    model.ProductImages.Add(image);
                }
            }

            return model;
        }
    }

}